import { Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { DrizzleService } from '../../db/drizzle.service';
import { LoginDto, RefreshTokenDto } from './dto/auth.schema';
import { users } from '../../db/schema';
import { and, eq } from 'drizzle-orm';
import { jwtConstants } from '../../constants/jwt.constant';
import { RoleService } from '../role/role.service';
import { MenuService } from '../menu/menu.service';
import { EncryptionService } from '../../common/services/encryption.service';
import { LoginLogService } from '../login-log/login-log.service';
import { ClientInfoService } from '../../common/services/client-info.service';
import { Request } from 'express';

@Injectable()
export class AuthService {
  constructor(
    private readonly drizzle: DrizzleService,
    private readonly jwtService: JwtService,
    private readonly roleService: RoleService,
    private readonly menuService: MenuService,
    private readonly encryptionService: EncryptionService,
    private readonly loginLogService: LoginLogService,
    private readonly clientInfoService: ClientInfoService,
  ) { }

  /**
   * 用户登录并颁发token
   */
  async login(loginDto: LoginDto, req: Request) {
    const { username, password } = loginDto;
    let loginLogDto: any = {
      userName: username,
      ipaddr: this.clientInfoService.getClientIp(req),
      loginLocation: '',
      status: '0', // 默认成功
      msg: '登录成功',
    };

    try {
      // 获取浏览器和操作系统信息
      const { browser, os } = this.clientInfoService.getBrowserInfo(req);
      loginLogDto.browser = browser;
      loginLogDto.os = os;
      loginLogDto.loginLocation = this.clientInfoService.getLocationByIp(loginLogDto.ipaddr);

      // 查找用户
      const userResult = await this.drizzle.db
        .select()
        .from(users)
        .where(
          and(
            eq(users.userName, username),
            eq(users.status, '0'),  // 0-正常状态
            eq(users.delFlag, '0')  // 0-未删除
          )
        );

      if (!userResult || userResult.length === 0) {
        loginLogDto.status = '1';
        loginLogDto.msg = '用户不存在';
        await this.loginLogService.create(loginLogDto);
        throw new UnauthorizedException('用户不存在');
      }

      const user = userResult[0];

      // 验证密码
      const isPasswordValid = await this.encryptionService.comparePassword(password, user.password);
      if (!isPasswordValid) {
        loginLogDto.status = '1';
        loginLogDto.msg = '密码错误';
        await this.loginLogService.create(loginLogDto);
        throw new UnauthorizedException('密码错误');
      }

      // 生成token
      const accessToken = await this.generateAccessToken(user);
      const refreshToken = await this.generateRefreshToken(user);

      // 获取用户角色
      const roles = await this.roleService.getRolesByUserId(user.userId);

      // 获取用户权限标识（直接从菜单获取，不查询sys_permission表）
      const roleIds = roles.map(role => role.roleId);
      const permissionKeys = await this.menuService.getUserPermissionKeysByRoleIds(roleIds);

      // 更新最后登录时间和IP
      await this.updateUserLoginInfo(user.userId, loginLogDto.ipaddr);

      // 记录成功登录日志
      await this.loginLogService.create(loginLogDto);

      return {
        accessToken,
        refreshToken,
        user: {
          userId: user.userId,
          userName: user.userName,
          nickName: user.nickName,
          avatar: user.avatar,
          roles: roles.map(role => ({
            roleId: role.roleId,
            roleName: role.roleName,
            roleKey: role.roleKey,
          })),
          permissions: permissionKeys.map(key => ({
            permissionKey: key,
          })),
        },
      };
    } catch (error) {
      // 如果还没有记录登录日志，这里记录失败日志
      if (loginLogDto.status === '0') {
        loginLogDto.status = '1';
        loginLogDto.msg = error.message || '登录失败';
        await this.loginLogService.create(loginLogDto);
      }
      throw error;
    }
  }

  /**
   * 刷新访问令牌
   */
  async refreshToken(refreshTokenDto: RefreshTokenDto) {
    try {
      const { refreshToken } = refreshTokenDto;

      // 验证刷新令牌
      const payload = this.jwtService.verify(refreshToken, {
        secret: jwtConstants.secret,
      });

      const userId = payload.sub;

      // 查找用户
      const userResult = await this.drizzle.db
        .select()
        .from(users)
        .where(
          and(
            eq(users.userId, userId),
            eq(users.status, '0'),
            eq(users.delFlag, '0')
          )
        );

      if (!userResult || userResult.length === 0) {
        throw new UnauthorizedException('无效的刷新令牌');
      }

      const user = userResult[0];

      // 生成新的访问令牌
      const accessToken = await this.generateAccessToken(user);

      return { accessToken };
    } catch (error) {
      throw new UnauthorizedException('无效的刷新令牌');
    }
  }

  /**
   * 生成访问令牌
   */
  private async generateAccessToken(user: any) {
    const payload = {
      sub: user.userId,
      username: user.userName,
    };

    return this.jwtService.sign(payload, {
      secret: jwtConstants.secret,
      expiresIn: jwtConstants.expiresIn,
    });
  }

  /**
   * 生成刷新令牌
   */
  private async generateRefreshToken(user: any) {
    const payload = {
      sub: user.userId,
      type: 'refresh',
    };

    return this.jwtService.sign(payload, {
      secret: jwtConstants.secret,
      expiresIn: jwtConstants.refreshExpiresIn,
    });
  }

  /**
   * 更新用户登录信息
   */
  private async updateUserLoginInfo(userId: number, loginIp: string = '127.0.0.1') {
    const loginDate = new Date();

    await this.drizzle.db
      .update(users)
      .set({
        loginIp,
        loginDate,
      })
      .where(eq(users.userId, userId));
  }
}
